qemu: Fix shift-insert behavior
authorKeir Fraser <keir.fraser@citrix.com>
Wed, 14 May 2008 08:16:40 +0000 (09:16 +0100)
committerKeir Fraser <keir.fraser@citrix.com>
Wed, 14 May 2008 08:16:40 +0000 (09:16 +0100)
This patch is related to Changeset 15635:7bdc9f6407d3
<http://xenbits.xensource.com/staging/xen-unstable.hg?rev/7bdc9f6407d3>
[PVFB] Fix shift key for graphical vnc display.
With above patch, if a user presses shift-insert, qemu sends shift
down, shift up, insert down and then another shift key down (see trace
below).  This makes it impossible to do shift insert pasting or use
guest hot shifted-Fkeys.

Shift Insert trace:
 do_key_event():1135 keycode:2a         shift down
    kbd_put_keycode():539 keycode:2a     send shift down
 do_key_event():1135 keycode:d2         insert down
    kbd_put_keycode():539 keycode:aa     send shift up
    kbd_put_keycode():539 keycode:e0     send insert down
    kbd_put_keycode():539 keycode:52
 do_key_event():1135 keycode:d2         insert up
    kbd_put_keycode():539 keycode:e0     send insert up
    kbd_put_keycode():539 keycode:d2
    kbd_put_keycode():539 keycode:2a     send shift down
 do_key_event():1135 keycode:2a         shift up
    kbd_put_keycode():539 keycode:aa     send shift up

This patch adds a check for the keycode being shiftable, something
other than a keypad key, f1-12 , insert, del , etc. before allowing
the press_shift_up() operation.

Signed-off-by: Pat Campbell <plc@novell.com>
tools/ioemu/keymaps.c
tools/ioemu/vnc.c

index b8ec39e61049c7a4341978b0a898e406844c3535..6d68d1a1f504bb6dcb259be1ebcef96a6a4c8729 100644 (file)
@@ -50,6 +50,7 @@ typedef struct {
     struct key_range *keypad_range;
     struct key_range *numlock_range;
     struct key_range *shift_range;
+    struct key_range *localstate_range;
 } kbd_layout_t;
 
 static void add_to_key_range(struct key_range **krp, int code) {
@@ -132,6 +133,10 @@ static kbd_layout_t *parse_keyboard_layout(const char *language,
                        add_to_key_range(&k->shift_range, keysym);
                        //fprintf(stderr, "shift keysym %04x keycode %d\n", keysym, keycode);
                    }
+                   if (rest && strstr(rest, "localstate")) {
+                       add_to_key_range(&k->localstate_range, keycode);
+                       //fprintf(stderr, "localstate keysym %04x keycode %d\n", keysym, keycode);
+                   }
 
                    /* if(keycode&0x80)
                       keycode=(keycode<<8)^0x80e0; */
@@ -221,3 +226,14 @@ static int keysymIsShift(void *kbd_layout, int keysym)
            return 1;
     return 0;
 }
+
+static int keycodeIsShiftable(void *kbd_layout, int keycode)
+{
+    kbd_layout_t *k = kbd_layout;
+    struct key_range *kr;
+
+    for (kr = k->localstate_range; kr; kr = kr->next)
+       if (keycode >= kr->start && keycode <= kr->end)
+           return 0;
+    return 1;
+}
index 0735d714f63bdff48fc918cf3debed4020053566..ba8f6cde71190b1aad2795f4138595fe41a084ae 100644 (file)
@@ -1307,6 +1307,7 @@ static void do_key_event(VncState *vs, int down, uint32_t sym)
     int keycode;
     int shift_keys = 0;
     int shift = 0;
+    int keypad = 0;
 
     if (is_graphic_console()) {
         if (sym >= 'A' && sym <= 'Z') {
@@ -1363,7 +1364,8 @@ static void do_key_event(VncState *vs, int down, uint32_t sym)
        return;
     }
 
-    if (keycodeIsKeypad(vs->kbd_layout, keycode)) {
+    keypad = keycodeIsKeypad(vs->kbd_layout, keycode);
+    if (keypad) {
         /* If the numlock state needs to change then simulate an additional
            keypress before sending this one.  This will happen if the user
            toggles numlock away from the VNC window.
@@ -1383,13 +1385,14 @@ static void do_key_event(VncState *vs, int down, uint32_t sym)
 
     if (is_graphic_console()) {
         /*  If the shift state needs to change then simulate an additional
-            keypress before sending this one.
+            keypress before sending this one. Ignore for non shiftable keys.
         */
         if (shift && !shift_keys) {
             press_key_shift_down(vs, down, keycode);
             return;
         }
-        else if (!shift && shift_keys) {
+        else if (!shift && shift_keys && !keypad &&
+                 keycodeIsShiftable(vs->kbd_layout, keycode)) {
             press_key_shift_up(vs, down, keycode);
             return;
         }